Merge "Do not concat exception class name in Timestamp compat"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 2 Feb 2018 21:38:29 +0000 (21:38 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 2 Feb 2018 21:38:29 +0000 (21:38 +0000)
22 files changed:
RELEASE-NOTES-1.31
includes/OutputPage.php
includes/SiteStats.php
includes/api/i18n/cs.json
includes/parser/ParserOptions.php
includes/skins/Skin.php
includes/specialpage/SpecialPage.php
languages/i18n/be-tarask.json
languages/i18n/gl.json
languages/i18n/hr.json
languages/i18n/is.json
languages/i18n/ko.json
languages/i18n/lij.json
languages/i18n/lv.json
languages/i18n/pl.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
resources/src/mediawiki/api/category.js
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/includes/Storage/RevisionStoreDbTest.php
tests/phpunit/includes/parser/ParserOptionsTest.php
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.category.test.js

index ad24852..e8b4422 100644 (file)
@@ -196,6 +196,17 @@ changes to languages because of Phabricator reports.
   used for that. Rather, setRef() existed as memory optimisation for PHP 4.
 * Passing false to ParserOptions::setWrapOutputClass() is deprecated. Use the
   'unwrap' transform to ParserOutput::getText() instead.
+* ParserOutput objects generated using a non-default value for
+  ParserOptions::setWrapOutputClass() can no longer be added to the parser
+  cache.
+* The following deprecated methods from the OutputPage class have been removed:
+  * OutputPage::addExtensionStyle(); deprecated in 1.27
+  * OutputPage::getExtStyle(); deprecated in 1.27
+  * OutputPage::setETag(); deprecated in 1.28 (obsolete no-op)
+  * OutputPage::setSquidMaxage(); deprecated in 1.27
+  * OutputPage::readOnlyPage(); deprecated in 1.25
+  * OutputPage::rateLimited(); deprecated in 1.25
+* The no-op method Skin::showIPinHeader(), deprecated in 1.27, was removed.
 
 == Compatibility ==
 MediaWiki 1.31 requires PHP 5.5.9 or later. Although HHVM 3.18.5 or later is supported,
index fc7fbf7..5fa66e8 100644 (file)
@@ -464,31 +464,6 @@ class OutputPage extends ContextSource {
                $this->mScripts .= $script;
        }
 
-       /**
-        * Register and add a stylesheet from an extension directory.
-        *
-        * @deprecated since 1.27 use addModuleStyles() or addStyle() instead
-        * @param string $url Path to sheet.  Provide either a full url (beginning
-        *             with 'http', etc) or a relative path from the document root
-        *             (beginning with '/').  Otherwise it behaves identically to
-        *             addStyle() and draws from the /skins folder.
-        */
-       public function addExtensionStyle( $url ) {
-               wfDeprecated( __METHOD__, '1.27' );
-               array_push( $this->mExtStyles, $url );
-       }
-
-       /**
-        * Get all styles added by extensions
-        *
-        * @deprecated since 1.27
-        * @return array
-        */
-       function getExtStyle() {
-               wfDeprecated( __METHOD__, '1.27' );
-               return $this->mExtStyles;
-       }
-
        /**
         * Add a JavaScript file out of skins/common, or a given relative path.
         * Internal use only. Use OutputPage::addModules() if possible.
@@ -714,13 +689,6 @@ class OutputPage extends ContextSource {
                $this->mAdditionalBodyClasses = array_merge( $this->mAdditionalBodyClasses, (array)$classes );
        }
 
-       /**
-        * @deprecated since 1.28 Obsolete - wgUseETag experiment was removed.
-        * @param string $tag
-        */
-       public function setETag( $tag ) {
-       }
-
        /**
         * Set whether the output should only contain the body of the article,
         * without any skin, sidebar, etc.
@@ -1988,15 +1956,6 @@ class OutputPage extends ContextSource {
                return Parser::stripOuterParagraph( $parsed );
        }
 
-       /**
-        * @param int $maxage
-        * @deprecated since 1.27 Use setCdnMaxage() instead
-        */
-       public function setSquidMaxage( $maxage ) {
-               wfDeprecated( __METHOD__, '1.27' );
-               $this->setCdnMaxage( $maxage );
-       }
-
        /**
         * Set the value of the "s-maxage" part of the "Cache-control" HTTP header
         *
@@ -2660,36 +2619,6 @@ class OutputPage extends ContextSource {
                return $text;
        }
 
-       /**
-        * Display a page stating that the Wiki is in read-only mode.
-        * Should only be called after wfReadOnly() has returned true.
-        *
-        * Historically, this function was used to show the source of the page that the user
-        * was trying to edit and _also_ permissions error messages. The relevant code was
-        * moved into EditPage in 1.19 (r102024 / d83c2a431c2a) and removed here in 1.25.
-        *
-        * @deprecated since 1.25; throw the exception directly
-        * @throws ReadOnlyError
-        */
-       public function readOnlyPage() {
-               if ( func_num_args() > 0 ) {
-                       throw new MWException( __METHOD__ . ' no longer accepts arguments since 1.25.' );
-               }
-
-               throw new ReadOnlyError;
-       }
-
-       /**
-        * Turn off regular page output and return an error response
-        * for when rate limiting has triggered.
-        *
-        * @deprecated since 1.25; throw the exception directly
-        */
-       public function rateLimited() {
-               wfDeprecated( __METHOD__, '1.25' );
-               throw new ThrottledError;
-       }
-
        /**
         * Show a warning about replica DB lag
         *
index ce87596..f10e6a2 100644 (file)
@@ -33,7 +33,6 @@ class SiteStats {
 
        /** @var bool */
        private static $loaded = false;
-
        /** @var int[] */
        private static $pageCount = [];
 
@@ -55,14 +54,6 @@ class SiteStats {
 
                self::$row = self::loadAndLazyInit();
 
-               # This code is somewhat schema-agnostic, because I'm changing it in a minor release -- TS
-               if ( !isset( self::$row->ss_total_pages ) && self::$row->ss_total_pages == -1 ) {
-                       # Update schema
-                       $u = new SiteStatsUpdate( 0, 0, 0 );
-                       $u->doUpdate();
-                       self::$row = self::doLoad( wfGetDB( DB_REPLICA ) );
-               }
-
                self::$loaded = true;
        }
 
@@ -84,20 +75,27 @@ class SiteStats {
                        }
                }
 
-               if ( !$wgMiserMode && !self::isSane( $row ) ) {
-                       // Normally the site_stats table is initialized at install time.
-                       // Some manual construction scenarios may leave the table empty or
-                       // broken, however, for instance when importing from a dump into a
-                       // clean schema with mwdumper.
-                       wfDebug( __METHOD__ . ": initializing damaged or missing site_stats\n" );
-
-                       SiteStatsInit::doAllAndCommit( wfGetDB( DB_REPLICA ) );
+               if ( !self::isSane( $row ) ) {
+                       if ( $wgMiserMode ) {
+                               // Start off with all zeroes, assuming that this is a new wiki or any
+                               // repopulations where done manually via script.
+                               SiteStatsInit::doPlaceholderInit();
+                       } else {
+                               // Normally the site_stats table is initialized at install time.
+                               // Some manual construction scenarios may leave the table empty or
+                               // broken, however, for instance when importing from a dump into a
+                               // clean schema with mwdumper.
+                               wfDebug( __METHOD__ . ": initializing damaged or missing site_stats\n" );
+                               SiteStatsInit::doAllAndCommit( wfGetDB( DB_REPLICA ) );
+                       }
 
                        $row = self::doLoad( wfGetDB( DB_MASTER ) );
                }
 
                if ( !self::isSane( $row ) ) {
                        wfDebug( __METHOD__ . ": site_stats persistently nonsensical o_O\n" );
+
+                       $row = (object)array_fill_keys( self::selectFields(), 0 );
                }
 
                return $row;
@@ -108,15 +106,7 @@ class SiteStats {
         * @return bool|stdClass
         */
        static function doLoad( $db ) {
-               return $db->selectRow( 'site_stats', [
-                               'ss_row_id',
-                               'ss_total_edits',
-                               'ss_good_articles',
-                               'ss_total_pages',
-                               'ss_users',
-                               'ss_active_users',
-                               'ss_images',
-                       ], [], __METHOD__ );
+               return $db->selectRow( 'site_stats', self::selectFields(), [], __METHOD__ );
        }
 
        /**
@@ -248,6 +238,21 @@ class SiteStats {
                return self::$pageCount[$ns];
        }
 
+       /**
+        * @return array
+        */
+       public static function selectFields() {
+               return [
+                       'ss_row_id',
+                       'ss_total_edits',
+                       'ss_good_articles',
+                       'ss_total_pages',
+                       'ss_users',
+                       'ss_active_users',
+                       'ss_images',
+               ];
+       }
+
        /**
         * Is the provided row of site stats sane, or should it be regenerated?
         *
@@ -404,6 +409,21 @@ class SiteStatsInit {
                }
        }
 
+       /**
+        * Insert a dummy row with all zeroes if no row is present
+        */
+       public static function doPlaceholderInit() {
+               $dbw = wfGetDB( DB_MASTER );
+               if ( $dbw->selectRow( 'site_stats', '1', [], __METHOD__ ) === false ) {
+                       $dbw->insert(
+                               'site_stats',
+                               array_fill_keys( SiteStats::selectFields(), 0 ),
+                               __METHOD__,
+                               [ 'IGNORE' ]
+                       );
+               }
+       }
+
        /**
         * Refresh site_stats
         */
index ea42e24..f90ae0f 100644 (file)
                        "Danny B.",
                        "LordMsz",
                        "Dvorapa",
-                       "Matěj Suchánek"
+                       "Matěj Suchánek",
+                       "Ilimanaq29"
                ]
        },
-       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Dokumentace]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api E-mailová konference]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Oznámení k API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Chyby a požadavky]\n</div>\n<strong>Stav:</strong> Všechny funkce uvedené na této stránce by měly fungovat, ale API se stále aktivně vyvíjí a může se kdykoli změnit. Upozornění na změny získáte přihlášením se k [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ e-mailové konferenci mediawiki-api-announce].\n\n<strong>Chybné požadavky:</strong> Pokud jsou do API zaslány chybné požadavky, bude vrácena HTTP hlavička s klíčem „MediaWiki-API-Error“ a hodnota této hlavičky a chybový kód budou nastaveny na stejnou hodnotu. Více informací najdete [[mw:Special:MyLanguage/API:Errors_and_warnings|v dokumentaci]].\n\n<strong>Testování:</strong> Pro jednoduché testování požadavků na API zkuste [[Special:ApiSandbox]].",
+       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Dokumentace]]\n* [[mw:Special:MyLanguage/API:FAQ|Otázky a odpovědi]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api E-mailová konference]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Oznámení k API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Chyby a požadavky]\n</div>\n<strong>Stav:</strong> Všechny funkce uvedené na této stránce by měly fungovat, ale API se stále aktivně vyvíjí a může se kdykoli změnit. Upozornění na změny získáte přihlášením se k [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ e-mailové konferenci mediawiki-api-announce].\n\n<strong>Chybné požadavky:</strong> Pokud jsou do API zaslány chybné požadavky, bude vrácena HTTP hlavička s klíčem „MediaWiki-API-Error“ a hodnota této hlavičky a chybový kód budou nastaveny na stejnou hodnotu. Více informací najdete [[mw:Special:MyLanguage/API:Errors_and_warnings|v dokumentaci]].\n\n<strong>Testování:</strong> Pro jednoduché testování požadavků na API zkuste [[Special:ApiSandbox]].",
        "apihelp-main-param-action": "Která akce se má provést.",
        "apihelp-main-param-format": "Formát výstupu.",
        "apihelp-main-param-maxlag": "Maximální zpoždění lze použít, když je MediaWiki nainstalováno na cluster s replikovanou databází. Abyste se vyhnuli zhoršování už tak špatného replikačního zpoždění, můžete tímto parametrem nechat klienta čekat, dokud replikační zpoždění neklesne pod uvedenou hodnotu. V případě příliš vysokého zpoždění se vrátí chybový kód „<samp>maxlag</samp>“ s hlášením typu „<samp>Waiting for $host: $lag seconds lagged</samp>“.<br />Více informací najdete v [[mw:Special:MyLanguage/Manual:Maxlag_parameter|příručce]].",
index 1405c45..ca8e739 100644 (file)
@@ -65,7 +65,6 @@ class ParserOptions {
                'stubthreshold' => true,
                'printable' => true,
                'userlang' => true,
-               'wrapclass' => true,
        ];
 
        /**
@@ -780,14 +779,17 @@ class ParserOptions {
        /**
         * CSS class to use to wrap output from Parser::parse()
         * @since 1.30
-        * @param string|bool $className Set false to disable wrapping.
-        *   Passing false is deprecated since MediaWiki 1.31
+        * @param string $className Class name to use for wrapping.
+        *   Passing false to indicate "no wrapping" was deprecated in MediaWiki 1.31.
         * @return string|bool Current value
         */
        public function setWrapOutputClass( $className ) {
                if ( $className === true ) { // DWIM, they probably want the default class name
                        $className = 'mw-parser-output';
                }
+               if ( $className === false ) {
+                       wfDeprecated( __METHOD__ . '( false )', '1.31' );
+               }
                return $this->setOption( 'wrapclass', $className );
        }
 
index c95f1f5..bd43255 100644 (file)
@@ -767,15 +767,6 @@ abstract class Skin extends ContextSource {
                return $subpages;
        }
 
-       /**
-        * @deprecated since 1.27, feature removed
-        * @return bool Always false
-        */
-       function showIPinHeader() {
-               wfDeprecated( __METHOD__, '1.27' );
-               return false;
-       }
-
        /**
         * @return string
         */
index 9f666c2..6828b4a 100644 (file)
@@ -615,6 +615,7 @@ class SpecialPage implements MessageLocalizer {
         * @deprecated since 1.23, use SpecialPage::getPageTitle
         */
        function getTitle( $subpage = false ) {
+               wfDeprecated( __METHOD__, '1.23' );
                return $this->getPageTitle( $subpage );
        }
 
index 6f0bd53..31e5aaa 100644 (file)
        "right-move-subpages": "Перанос старонак разам зь іх падстаронкамі",
        "right-move-rootuserpages": "перанос карэнных старонак удзельнікаў",
        "right-move-categorypages": "перанос старонак катэгорыяў",
-       "right-movefile": "перайменаваньне файлаў",
+       "right-movefile": "Ð\9fерайменаваньне файлаў",
        "right-suppressredirect": "не ствараць перанакіраваньне са старой назвы пасьля пераносу старонкі",
        "right-upload": "загрузка файлаў",
        "right-reupload": "перазапіс існуючых файлаў",
index 5193c0b..5be7056 100644 (file)
        "postedit-confirmation-created": "Creouse a páxina.",
        "postedit-confirmation-restored": "Restaurouse a páxina.",
        "postedit-confirmation-saved": "Gardouse a súa edición.",
+       "postedit-confirmation-published": "A súa edición foi publicada.",
        "edit-already-exists": "Non se pode crear a nova páxina.\nEsta xa existe.",
        "defaultmessagetext": "Texto predeterminado",
        "content-failed-to-parse": "Erro ao analizar o contido de \"$2\" para o modelo de $1: $3",
        "lockmanager-fail-closelock": "Non se puido pechar o ficheiro de peche de \"$1\".",
        "lockmanager-fail-deletelock": "Non se puido borrar o ficheiro de peche de \"$1\".",
        "lockmanager-fail-acquirelock": "Non se puido obter o peche de \"$1\".",
-       "lockmanager-fail-openlock": "Non se puido abrir o ficheiro de peche de \"$1\".",
+       "lockmanager-fail-openlock": "Non se puido abrir o ficheiro de bloqueo de \"$1\". Revise que o directorio de cargas estea configurado correctamente e que o seu servidor web teña permisos de escritura nese directorio. Consulte https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory para obter máis información.",
        "lockmanager-fail-releaselock": "Non se puido liberar o peche de \"$1\".",
        "lockmanager-fail-db-bucket": "Non se puido contactar cos peches de bases de datos suficientes no cubo $1.",
        "lockmanager-fail-db-release": "Non se puideron liberar os peches na base de datos $1.",
        "doubleredirects": "Redireccións dobres",
        "doubleredirectstext": "Esta lista contén as páxinas que redirixen cara a outras páxinas de redirección.\nCada ringleira contén ligazóns cara á primeira e segunda redireccións, así como a primeira liña de texto da segunda páxina, que é frecuentemente o artigo \"real\", á que a primeira redirección debera apuntar.\nAs entradas <del>riscadas</del> xa foron resoltas.",
        "double-redirect-fixed-move": "Trasladouse a páxina \"[[$1]]\".\nActualizouse automaticamente e agora é unha redirección cara a \"[[$2]]\".",
-       "double-redirect-fixed-maintenance": "Arranxo automaticamente a redirección dobre entre \"[[$1]]\" e \"[[$2]]\" como tarefa de mantemento.",
+       "double-redirect-fixed-maintenance": "Arranxo automático da redirección dobre entre \"[[$1]]\" e \"[[$2]]\" nunha tarefa de mantemento",
        "double-redirect-fixer": "Amañador de redireccións",
        "brokenredirects": "Redireccións rotas",
        "brokenredirectstext": "As seguintes redireccións ligan cara a páxinas que non existen:",
index 060c444..5fd0fe9 100644 (file)
        "rcfilters-advancedfilters": "Napredni filtri",
        "rcfilters-limit-title": "Rezultata za prikaz",
        "rcfilters-limit-and-date-label": "{{PLURAL:$1|$1 izmjena|$1 izmjene|$1 izmjena}}, $2",
-       "rcfilters-date-popup-title": "Vremensko razdoblje za pretragu",
+       "rcfilters-date-popup-title": "Razdoblje za pretraživanje",
        "rcfilters-days-title": "Nedavnih dana",
        "rcfilters-hours-title": "Nedavnih sati",
        "rcfilters-days-show-days": "$1 {{PLURAL:$1|dan|dana}}",
index 8aeac3c..f0d3cd3 100644 (file)
        "rcfilters-activefilters": "Virkar síur",
        "rcfilters-advancedfilters": "Ítarlegar síur",
        "rcfilters-limit-title": "Breytingar sem á að birta",
+       "rcfilters-limit-and-date-label": "$1 {{PLURAL:$1|breyting|breytingar}}, $2",
        "rcfilters-date-popup-title": "Tímarammi sem á að leita í",
        "rcfilters-days-title": "Síðustu daga",
        "rcfilters-hours-title": "Síðustu klukkutíma",
        "rcfilters-highlighted-filters-list": "Áherslulitað: $1",
        "rcfilters-quickfilters": "Vistaðar síur",
        "rcfilters-quickfilters-placeholder-title": "Engar síur vistaðar",
-       "rcfilters-quickfilters-placeholder-description": "Til þess að vista þínar síustillingar og nota þær aftur seinna, smelltu á bókamerkistáknið undir Virkum síum hér fyrir neðan.",
+       "rcfilters-quickfilters-placeholder-description": "Til þess að vista síustillingarnar þínar og nota þær aftur seinna, smelltu á bókamerkistáknið undir 'Virkar síur' hér fyrir neðan.",
        "rcfilters-savedqueries-defaultlabel": "Vistaðar síur",
        "rcfilters-savedqueries-rename": "Endurnefna",
        "rcfilters-savedqueries-setdefault": "Setja sem sjálfgefið",
        "rcfilters-liveupdates-button-title-off": "Sýna nýjar breytingar um leið og þær gerast",
        "rcfilters-watchlist-markseen-button": "Merkja allar breytingar sem skoðaðar",
        "rcfilters-watchlist-edit-watchlist-button": "Breyta þínum lista yfir vaktaðar síður",
+       "rcfilters-filter-showlinkedfrom-label": "Sýna breytingar á síðum sem tengt er í frá",
+       "rcfilters-filter-showlinkedfrom-option-label": "<strong>Síður sem tengt er í</strong> frá valinni síðu",
+       "rcfilters-filter-showlinkedto-label": "Sýna breytingar á síðum sem tengjast í",
+       "rcfilters-filter-showlinkedto-option-label": "<strong>Síður sem tengjast í</strong> valda síðu",
        "rcfilters-target-page-placeholder": "Settu inn síðuheiti (eða flokk)",
        "rcnotefrom": "Að neðan {{PLURAL:$5|er breyting síðan|eru breytingar síðan}} <strong>$3, $4</strong> (allt að <strong>$1</strong> sýndar).",
        "rclistfromreset": "Endurstilla dagsetningarval",
index 340f427..ef12e21 100644 (file)
        "postedit-confirmation-created": "문서가 만들어졌습니다.",
        "postedit-confirmation-restored": "문서가 되돌려졌습니다.",
        "postedit-confirmation-saved": "편집을 저장했습니다.",
+       "postedit-confirmation-published": "편집이 게시되었습니다.",
        "edit-already-exists": "새 문서를 만들 수 없습니다.\n문서가 이미 존재합니다.",
        "defaultmessagetext": "기본 메시지 글",
        "content-failed-to-parse": "$1 모델에 대한 $2 내용을 구문 분석하는 데 실패했습니다: $3",
index 171b989..74558b9 100644 (file)
        "site-atom-feed": "Feed Atom de $1",
        "page-rss-feed": "Feed RSS pe \"$1\"",
        "page-atom-feed": "Feed Atom pe \"$1\"",
-       "red-link-title": "$1 (a pàgina no esiste)",
+       "red-link-title": "$1 (a pàgina a no existe)",
        "sort-descending": "Ordine decrescente",
        "sort-ascending": "Ordine crescente",
        "nstab-main": "Pàgina",
        "userlogin-yourname-ph": "Inserisci o teu nómme uténte",
        "createacct-another-username-ph": "Scrivi o teu nomme utente",
        "yourpassword": "Pòula segretta:",
-       "userlogin-yourpassword": "Ciâve",
+       "userlogin-yourpassword": "Inserisci a teu ciâve",
        "userlogin-yourpassword-ph": "Scrivi a tu poula segretta.",
        "createacct-yourpassword-ph": "Scrivi 'na poula segretta.",
        "yourpasswordagain": "Riscrivi a pòula segrétta:",
        "emailuserfooter": "Questa email a l'è stæta {{GENDER:$1|inviâ}} da $1 a {{GENDER:$2|$2}} a traverso a fonçion \"{{int:emailuser}}\" insce {{SITENAME}}. Se {{GENDER:$2|ti ghe rispondi}}, a to email de risposta a saiâ spedia direttamente {{GENDER:$1|a-o|a-a}} mittente originâ, rivelando{{GENDER:$1|ghe}} o {{GENDER:$2|to}} adresso de posta elettronica.",
        "usermessage-summary": "Messaggio de scistema",
        "usermessage-editor": "Messaggê de scistema",
-       "watchlist": "Ã\92servòi speciâli",
-       "mywatchlist": "òservòi speciâli",
+       "watchlist": "Ã\92servæ speciâli",
+       "mywatchlist": "òservæ speciâli",
        "watchlistfor2": "Pe $1 $2",
        "nowatchlist": "A lista di öservæ speciali a l'è voeua.",
        "watchlistanontext": "Pe vixualizzâ e modificâ l'elenco di öservæ l'è necessaio eseguî l'accesso.",
index 1c96495..ff62ec0 100644 (file)
        "watchlist-details": "Tu uzraugi $1 {{PLURAL:$1|lapas|lapu|lapas}} (neieskaitot diskusiju lapas).",
        "wlheader-enotif": "E-pasta paziņojumi ir ieslēgti.",
        "wlheader-showupdated": "Lapas, kas ir tikušas izmainītas, kopš pēdējoreiz skatījies tās, tiek rādītas <strong>trekninātā</strong> rakstā.",
+       "wlnote": "Zemāk {{PLURAL:$1|redzamas <strong>$1</strong> izmaiņas|redzama <strong>$1</strong> izmaiņa|redzamas <strong>$1</strong> izmaiņas}} {{PLURAL:$2|pēdējās <strong>$2</strong> stundās|pēdējā <strong>$2</strong> stundā|pēdējās <strong>$2</strong> stundās}} uz $3 $4.",
        "wlshowlast": "Rādīt pēdējās $1 stundas $2 dienas",
        "watchlist-hide": "Slēpt",
        "watchlist-submit": "Rādīt",
index 58bd82f..92efb1e 100644 (file)
        "rcfilters-watchlist-markseen-button": "Oznacz wszystkie zmiany jako obejrzane",
        "rcfilters-watchlist-edit-watchlist-button": "Edytuj swoją listę obserwowanych stron",
        "rcfilters-watchlist-showupdated": "<strong>Wytłuszczono</strong> strony, których nie odwiedził{{GENDER:|e|a|e}}ś od czasu zapisania ostatnich zmian.",
-       "rcfilters-preference-label": "Wyłącz ulepszenia strony Ostatnie zmiany",
+       "rcfilters-preference-label": "Wyłącz ulepszenia strony Ostatnich zmian",
        "rcfilters-preference-help": "Wycofuje wszystkie zmiany interfejsu z 2017 i narzędzia dodane od tamtej pory.",
        "rcfilters-filter-showlinkedfrom-label": "Pokaż zmiany na stronach linkowanych z",
        "rcfilters-filter-showlinkedfrom-option-label": "<strong>Strony linkowane z</strong> zaznaczonej strony",
index f1e57fa..03701e7 100644 (file)
        "log-action-filter-managetags-activate": "активирање ознаке",
        "log-action-filter-managetags-deactivate": "деактивирање ознаке",
        "log-action-filter-move-move": "премештање без преснимавања преусмерења",
-       "log-action-filter-move-move_redir": "Ð\9fÑ\80емеÑ\88Ñ\82аÑ\9aе Ñ\81а Ð¿Ñ\80епиÑ\81ивањем преусмерења",
+       "log-action-filter-move-move_redir": "пÑ\80емеÑ\88Ñ\82аÑ\9aе Ñ\81а Ð¿Ñ\80еÑ\81нимавањем преусмерења",
        "log-action-filter-newusers-create": "отворио анониман корисник",
        "log-action-filter-newusers-create2": "отворио регистрован корисник",
        "log-action-filter-newusers-autocreate": "аутоматски отворен",
        "log-action-filter-protect-protect": "закључавање",
        "log-action-filter-protect-modify": "измена закључавања",
        "log-action-filter-protect-unprotect": "уклањање закључавања",
-       "log-action-filter-protect-move_prot": "Ð\9fремештање заштите",
+       "log-action-filter-protect-move_prot": "премештање заштите",
        "log-action-filter-rights-rights": "ручно",
        "log-action-filter-rights-autopromote": "аутоматски",
-       "log-action-filter-upload-upload": "Ð\9dово отпремање",
+       "log-action-filter-upload-upload": "ново отпремање",
        "log-action-filter-upload-overwrite": "промена постојећег",
        "authmanager-authplugin-setpass-failed-title": "Неуспешна промена лозинке",
        "authmanager-email-label": "Имејл",
index 467e68b..b9dd55a 100644 (file)
        "mw-widgets-usersmultiselect-placeholder": "Dodaj još...",
        "randomrootpage": "Slučajna korenska stranica",
        "log-action-filter-all": "Sve",
-       "log-action-filter-move-move_redir": "Premeštanje sa prepisivanjem preusmerenja",
-       "log-action-filter-protect-move_prot": "Premeštanje zaštite",
-       "log-action-filter-upload-upload": "Novo otpremanje",
+       "log-action-filter-move-move_redir": "premeštanje sa presnimavanjem preusmerenja",
+       "log-action-filter-protect-move_prot": "premeštanje zaštite",
+       "log-action-filter-upload-upload": "novo otpremanje",
        "authmanager-email-label": "Imejl",
        "authmanager-email-help": "Imejl adresa",
        "changecredentials": "Promjena akreditiva",
index 04462e3..85df90e 100644 (file)
                        var apiPromise = this.get( {
                                formatversion: 2,
                                prop: 'categoryinfo',
-                               titles: String( title )
+                               titles: [ String( title ) ]
                        } );
 
                        return apiPromise
                                .then( function ( data ) {
-                                       return !!data.query.pages[ 0 ].categoryinfo;
+                                       return !!(
+                                               data.query && // query is missing on title=""
+                                               data.query.pages && // query.pages is missing on title="#" or title="mw:"
+                                               data.query.pages[ 0 ].categoryinfo
+                                       );
                                } )
                                .promise( { abort: apiPromise.abort } );
                },
                        var apiPromise = this.get( {
                                formatversion: 2,
                                prop: 'categories',
-                               titles: String( title )
+                               titles: [ String( title ) ]
                        } );
 
                        return apiPromise
                                .then( function ( data ) {
-                                       var page = data.query.pages[ 0 ];
+                                       var page;
 
+                                       if ( !data.query || !data.query.pages ) {
+                                               return false;
+                                       }
+                                       page = data.query.pages[ 0 ];
                                        if ( !page.categories ) {
                                                return false;
                                        }
index fe8c917..3f4c8c0 100644 (file)
@@ -1080,6 +1080,8 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                        }
                }
 
+               SiteStatsInit::doPlaceholderInit();
+
                User::resetIdByNameCache();
 
                // Make sysop user
index 8185670..6c90854 100644 (file)
@@ -34,6 +34,14 @@ use WikitextContent;
  */
 class RevisionStoreDbTest extends MediaWikiTestCase {
 
+       public function setUp() {
+               parent::setUp();
+               $this->tablesUsed[] = 'archive';
+               $this->tablesUsed[] = 'page';
+               $this->tablesUsed[] = 'revision';
+               $this->tablesUsed[] = 'comment';
+       }
+
        /**
         * @return LoadBalancer
         */
index 232b0bb..d55372c 100644 (file)
@@ -21,7 +21,6 @@ class ParserOptionsTest extends MediaWikiTestCase {
                        'stubthreshold' => true,
                        'printable' => true,
                        'userlang' => true,
-                       'wrapclass' => true,
                ];
        }
 
@@ -67,6 +66,9 @@ class ParserOptionsTest extends MediaWikiTestCase {
                        'Non-in-key options are not ok' => [ false, [
                                'removeComments' => false,
                        ] ],
+                       'Non-in-key options are not ok (2)' => [ false, [
+                               'wrapclass' => 'foobar',
+                       ] ],
                        'Canonical override, not default (1)' => [ true, [
                                'tidy' => true,
                        ] ],
@@ -213,7 +215,7 @@ class ParserOptionsTest extends MediaWikiTestCase {
                $wgHooks['ParserOptionsRegister'] = [];
                $this->assertSame( [
                        'dateformat', 'numberheadings', 'printable', 'stubthreshold',
-                       'thumbsize', 'userlang', 'wrapclass',
+                       'thumbsize', 'userlang'
                ], ParserOptions::allCacheVaryingOptions() );
 
                self::clearCache();
@@ -231,7 +233,7 @@ class ParserOptionsTest extends MediaWikiTestCase {
                };
                $this->assertSame( [
                        'dateformat', 'foo', 'numberheadings', 'printable', 'stubthreshold',
-                       'thumbsize', 'userlang', 'wrapclass',
+                       'thumbsize', 'userlang'
                ], ParserOptions::allCacheVaryingOptions() );
        }
 
index 8ad1290..50fa6d1 100644 (file)
                        );
                } );
        } );
+
+       QUnit.test( '.isCategory("")', function ( assert ) {
+               this.server.respondWith( /titles=$/, [
+                       200,
+                       { 'Content-Type': 'application/json' },
+                       '{"batchcomplete":true}'
+               ] );
+               return new mw.Api().isCategory( '' ).then( function ( response ) {
+                       assert.equal( response, false );
+               } );
+       } );
+
+       QUnit.test( '.isCategory("#")', function ( assert ) {
+               this.server.respondWith( /titles=%23$/, [
+                       200,
+                       { 'Content-Type': 'application/json' },
+                       '{"batchcomplete":true,"query":{"normalized":[{"fromencoded":false,"from":"#","to":""}]}}'
+               ] );
+               return new mw.Api().isCategory( '#' ).then( function ( response ) {
+                       assert.equal( response, false );
+               } );
+       } );
+
+       QUnit.test( '.isCategory("mw:")', function ( assert ) {
+               this.server.respondWith( /titles=mw%3A$/, [
+                       200,
+                       { 'Content-Type': 'application/json' },
+                       '{"batchcomplete":true,"query":{"interwiki":[{"title":"mw:","iw":"mw"}]}}'
+               ] );
+               return new mw.Api().isCategory( 'mw:' ).then( function ( response ) {
+                       assert.equal( response, false );
+               } );
+       } );
+
+       QUnit.test( '.isCategory("|")', function ( assert ) {
+               this.server.respondWith( /titles=%1F%7C$/, [
+                       200,
+                       { 'Content-Type': 'application/json' },
+                       '{"batchcomplete":true,"query":{"pages":[{"title":"|","invalidreason":"The requested page title contains invalid characters: \\"|\\".","invalid":true}]}}'
+               ] );
+               return new mw.Api().isCategory( '|' ).then( function ( response ) {
+                       assert.equal( response, false );
+               } );
+       } );
+
+       QUnit.test( '.getCategories("")', function ( assert ) {
+               this.server.respondWith( /titles=$/, [
+                       200,
+                       { 'Content-Type': 'application/json' },
+                       '{"batchcomplete":true}'
+               ] );
+               return new mw.Api().getCategories( '' ).then( function ( response ) {
+                       assert.equal( response, false );
+               } );
+       } );
+
+       QUnit.test( '.getCategories("#")', function ( assert ) {
+               this.server.respondWith( /titles=%23$/, [
+                       200,
+                       { 'Content-Type': 'application/json' },
+                       '{"batchcomplete":true,"query":{"normalized":[{"fromencoded":false,"from":"#","to":""}]}}'
+               ] );
+               return new mw.Api().getCategories( '#' ).then( function ( response ) {
+                       assert.equal( response, false );
+               } );
+       } );
+
+       QUnit.test( '.getCategories("mw:")', function ( assert ) {
+               this.server.respondWith( /titles=mw%3A$/, [
+                       200,
+                       { 'Content-Type': 'application/json' },
+                       '{"batchcomplete":true,"query":{"interwiki":[{"title":"mw:","iw":"mw"}]}}'
+               ] );
+               return new mw.Api().getCategories( 'mw:' ).then( function ( response ) {
+                       assert.equal( response, false );
+               } );
+       } );
+
+       QUnit.test( '.getCategories("|")', function ( assert ) {
+               this.server.respondWith( /titles=%1F%7C$/, [
+                       200,
+                       { 'Content-Type': 'application/json' },
+                       '{"batchcomplete":true,"query":{"pages":[{"title":"|","invalidreason":"The requested page title contains invalid characters: \\"|\\".","invalid":true}]}}'
+               ] );
+               return new mw.Api().getCategories( '|' ).then( function ( response ) {
+                       assert.equal( response, false );
+               } );
+       } );
+
 }( mediaWiki ) );